package com.ws.gc.web.auth;
import com.ws.gc.web.auth.handler.CustomAuthenticationEntryPoint;
import com.ws.gc.web.auth.handler.LogoutAuthSuccessHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.configurers.SessionManagementConfigurer;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.web.server.SecurityWebFilterChain;
import org.springframework.security.web.server.ServerAuthenticationEntryPoint;
import org.springframework.security.web.server.authentication.ServerAuthenticationFailureHandler;
import org.springframework.security.web.server.authentication.ServerAuthenticationSuccessHandler;
import org.springframework.security.web.server.context.ServerSecurityContextRepository;
import org.springframework.security.web.server.context.WebSessionServerSecurityContextRepository;
import org.springframework.web.reactive.config.WebFluxConfigurer;
import org.springframework.web.server.session.HeaderWebSessionIdResolver;
import org.springframework.web.server.session.WebSessionIdResolver;

@EnableWebFluxSecurity
@Configuration
public class WebSecurityConfig {

    private ServerAuthenticationSuccessHandler authSuccessHandler;
    private ServerAuthenticationFailureHandler authFailureHandler;
    private LogoutAuthSuccessHandler logoutAuthSuccessHandler;
    private CustomUserDetailsService userDetailsService;

    @Autowired
    public WebSecurityConfig(ServerAuthenticationSuccessHandler authSuccessHandler,
                             ServerAuthenticationFailureHandler authFailureHandler,
                             LogoutAuthSuccessHandler logoutAuthSuccessHandler,
                             CustomUserDetailsService userDetailsService){
        this.userDetailsService = userDetailsService;
        this.authSuccessHandler = authSuccessHandler;
        this.authFailureHandler = authFailureHandler;
        this.logoutAuthSuccessHandler = logoutAuthSuccessHandler;
    }



    @Bean
    public ServerAuthenticationEntryPoint authenticationEntryPoint() {
        return new CustomAuthenticationEntryPoint();
    }


    @Bean
    public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
        http.authorizeExchange()
                .pathMatchers("/static/**").permitAll()
                .pathMatchers( "/login/*","/logout/*").permitAll()
                .anyExchange().authenticated()
                .and().exceptionHandling().authenticationEntryPoint(authenticationEntryPoint())
                .and()
                .formLogin().loginPage("/login")
                .authenticationSuccessHandler(authSuccessHandler)
                .authenticationFailureHandler(authFailureHandler)
                .and().csrf().disable()
                .logout()
                .logoutUrl("/logout")
                .logoutSuccessHandler(logoutAuthSuccessHandler).and().securityContextRepository(serverSecurityContextRepository());
        return http.build();
    }

    @Bean
    SessionManagementConfigurer configurer(){
        SessionManagementConfigurer configurer = new SessionManagementConfigurer();
        configurer.maximumSessions(1).expiredUrl("/login");
        return configurer;
    }

    @Bean
    ServerSecurityContextRepository serverSecurityContextRepository() {
        return new WebSessionServerSecurityContextRepository();
    }

}
